package cn.example.web.db.dao;

import org.artifact.core.db.MySqlDao;
import org.artifact.core.lang.StrPlus;
import java.util.List;
import java.util.ArrayList;
import java.text.MessageFormat;
import java.util.function.BiFunction;
import org.artifact.core.db.BaseBean;
import cn.hutool.core.map.MapUtil;
import java.util.Map;
import java.util.HashMap;
import org.artifact.core.db.BaseDao;
import cn.example.web.db.bean.User;
import static cn.hutool.core.util.ObjectUtil.equal;

public abstract class UserDAO extends MySqlDao<User>{
	
	protected final String sqlAllColumn = "id, account, password, permission, channel_id, channel_pack_id, device_token, device_name, device_id, os_name, os_version, phone_number, email, language, client_version, create_date, modified_date";

	protected final String sqlAllPla = "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?";

	@Override
	protected String getDBName() {
		return "example_web";
	}
	
	@Override
	protected String getTableName() {
		return "t_user";
	}
	
	@Override
	protected Class<User> getEntityClass(){
		return User.class;
	}
	
	@Override
	protected User createEntity() {
		return new User() {};
	}

	@Override
	protected String getPKFieldName() {
		return "id";
	}
	
	// 根据主键导出
	public Map<String,Object> exportByPrimaryKey(long id,BiFunction<BaseDao,BaseBean,Object> function){
		return export(findByPrimaryKey(id),function);
	}
	
	public Map<String,Object> exportByAccountChannelId(String account ,long channelId,BiFunction<BaseDao,BaseBean,Object> function){
		return export(findByAccountChannelId(account ,channelId),function);
	}
	
	public Map<String,Object> export(User user,BiFunction<BaseDao,BaseBean,Object> function){
		Map<String,Object> data = new HashMap<>();
		data.put("self", function.apply(this,user));
		return data;
	}
	
	public List<Map<String,Object>> export(List<User> users,BiFunction<BaseDao,BaseBean,Object> function){
		List<Map<String,Object>> data = new ArrayList<>();
		for(User user : users){
			data.add(export(user,function));
		}
		return data;
	}


	public User _import(Map<String,Object> data,BiFunction<BaseDao,Map,BaseBean> function){
	    User user = createEntity();
	    user = (User)function.apply(this,MapUtil.get(data,"self",Map.class));

        return user;
    }

    public List<User> _import(List<Map<String,Object>> data,BiFunction<BaseDao,Map,BaseBean> function){
        List<User> list = new ArrayList<>();
        for(Map<String,Object> map : data){
            list.add(_import(map,function));
        }
        return list;
    }
	
	
	@Override
	public boolean createTable(){
		StrPlus plus = StrPlus.b("CREATE TABLE IF NOT EXISTS `t_user` (");
		plus.a("  `id` bigint(20) NOT NULL COMMENT '主键',");
		plus.a("  `account` varchar(45) NOT NULL COMMENT '账号',");
		plus.a("  `password` varchar(45) NOT NULL COMMENT '密码',");
		plus.a("  `permission` varchar(45) NOT NULL COMMENT '权限',");
		plus.a("  `channel_id` varchar(45) NOT NULL COMMENT '渠道ID',");
		plus.a("  `channel_pack_id` varchar(45) NOT NULL COMMENT '渠道包ID',");
		plus.a("  `device_token` varchar(45) NOT NULL COMMENT '设备Token',");
		plus.a("  `device_name` varchar(45) NOT NULL COMMENT '设备名称',");
		plus.a("  `device_id` varchar(45) NOT NULL COMMENT '设备ID',");
		plus.a("  `os_name` varchar(45) NOT NULL COMMENT '系统名称',");
		plus.a("  `os_version` varchar(45) NOT NULL COMMENT '系统版本',");
		plus.a("  `phone_number` varchar(45) NOT NULL COMMENT '手机号',");
		plus.a("  `email` varchar(45) NOT NULL COMMENT '邮箱',");
		plus.a("  `language` varchar(45) NOT NULL COMMENT '语言',");
		plus.a("  `client_version` varchar(45) NOT NULL COMMENT '客户端版本',");
		plus.a("  `create_date` datetime NOT NULL COMMENT '创建时间',");
		plus.a("  `modified_date` datetime NOT NULL COMMENT '修改时间',");
		plus.a("  PRIMARY KEY (`id`),");
		plus.a("  UNIQUE KEY (`account`,`channel_id`)");
		plus.a(") ENGINE=InnoDB DEFAULT CHARSET=utf8  COMMENT='用户';");
		update(plus.e());
		return true;
	}
	
	@Override
	protected String getSaveSql() {
		return MessageFormat.format("REPLACE INTO {0} ({1}) VALUES ({2})",getTableName(),sqlAllColumn,sqlAllPla);
	}

	@Override
	protected String getDeleteSql() {
		return MessageFormat.format("DELETE FROM {0} WHERE id = ?",getTableName());
	}
	
	public User findByAccountChannelId(String account ,long channelId){
		String sql = MessageFormat.format("SELECT {0} FROM {1} WHERE account = ? AND channel_id = ?",sqlAllColumn,getTableName());
		return resultFirst(()->{
			return findFirst(sql,new Object[]{account ,channelId});
		}, t -> {
			return equal(t.getAccount(), account) && equal(t.getChannelId(), channelId);
		}) ;
	}
	
}